# Python的标准库提供了两个模块：
# _thread和threading，_thread是低级模块，threading是高级模块，
# 对_thread进行了封装。绝大多数情况下，我们只需要使用threading这个高级模块。
import time, threading


def looping():
    print('thread running  %s .' % threading.current_thread().getName())
    n = 0
    while n < 3:
        n = n + 1
        print('thread %s >>> %s' % (threading.current_thread().name, n))
        time.sleep(1)
    print('thread %s ended.' % threading.current_thread().name)


# Python的threading模块有个current_thread()函数，它永远返回当前线程的实例
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=looping, name='LoopThread')
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)
print('*****************************没上锁LOCK****************************************')
# 线程和多进程最大的不同在于，多进程中，同一个变量，各自有一份拷贝存在于每个进程中，互不影响，而多线程中，所有变量都由所有线程共享，
# 所以，任何一个变量都可以被任何一个线程修改，因此，线程之间共享数据最大的危险在于多个线程同时改一个变量，把内容给改乱
# 假定这是你的银行存款:
# 下面案例全局变量balance为0 ，有时候会打印8
balance = 0


def change_it(n):
    # 先存后取，结果应该为0:
    global balance
    balance = balance + n
    balance = balance - n


def run_thread(n):
    for i in range(100000):
        change_it(n)


t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t3 = threading.Thread(target=run_thread, args=(3,))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(balance)
# 如果我们要确保balance计算正确，就要给change_it()上一把锁，当某个线程开始执行change_it()时，我们说
# 、该线程因为获得了锁，因此其他线程不能同时执行change_it()，只能等待，
# 直到锁被释放后，获得该锁以后才能改。由于锁只有一个，、无论多少线程，同一时刻最多只有一个线程持有该锁，
# 所以，不会造成修改的冲突。创建一个锁就是通过threading.Lock()来实现：
# 阻止了多线程并发执行，包含锁的某段代码实际上只能以单线程模式执行，效率就大大地下降，会出现死锁
print('*****************************上锁了。。****************************************')
lock = threading.Lock()
balance2 = 0


def change_it2(n):
    # 先存后取，结果应该为0:
    global balance2
    balance2 = balance2 + n
    balance2 = balance2 - n


def run_threadTwo(n):
    for i in range(100000):
        # 先要获取锁:
        lock.acquire()
        try:
            # 放心地改吧:
            change_it2(n)
        finally:
            # 改完了一定要释放锁:
            lock.release()


t11 = threading.Thread(target=run_threadTwo, args=(5,))
t22 = threading.Thread(target=run_threadTwo, args=(8,))

t11.start()
t22.start()
t11.join()
t22.join()
print(balance2)
